//
// process.h
// libprotea
// Tools Library for the Protea Project / Process/Thread functionality
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// Please send correspondence to:
// 
// theproteaproject@gmail.com
//

#ifndef __PROTEA_PROCESS_H__
#define __PROTEA_PROCESS_H__

/*
	\file process.h
	\brief OS independent routines for process handling
*/
#include "transport.h"

class XCAppInterface;

//
// Used to create a new process
//
struct create_process_return {
	PORT_HANDLE handle;
	pid_t id;
};

// Application startup information
//
// init_message structure is based on this one
//
struct app_start_message {
	// What app are we? (used for Substation to App communication)
	char appl_name[ 32 ];
	int appl_nbr;

	// Debug information
	int debug_type_filter;
	int debug_level_cutoff[ num_tc ];

	// Worker threads
	int worker_threads;

	// Authentication information
	int authentication_method;
	int authentication_parm_len;

	// Misc settings
	// NOTE: When adding new app settings, make appropriate changes in process.h,
	// AppInterface.h, AppInterface.cpp (XCAppInterface::StartApp),
	// substation.cpp (XCSubstation::StartApps), 
	// parms_xml.h and parms_xml.cpp (parms_reader::HandleSettings, parms_reader::CheckDebugTags)
	int admin_email_len;
	int smtp_len;
	int printer_len;
	int fop_location_len;

	// Support for .NET CLI applications
	bool NETapp;

	char data[ 1024 ];
};

struct process_info {
	char* 			file;			// Filename of process
	pid_t			pid;			// Process ID
	bool			active;			// Is it active?
	XCMsgPort*		port;			// It's message port

	XCTransport*	server;
	XCTransport*	client;

	app_start_message startup;		// Record startup parameters
	process_info*	next;			// Pointer to next process
};

typedef process_info* process_info_ptr;

// Thread functions
__EXPORT THREAD_HANDLE	XCCreateThread( XCThreadProc proc, void* parm );
__EXPORT long			XCGetThreadIdentifier();
__EXPORT void			XCJoinThread( THREAD_HANDLE thread );

// Process functions
__EXPORT pid_t			XCGetProcessIdentifier();
__EXPORT process_info*	XCAddProcess   ( process_info_ptr& plist );
__EXPORT void			XCDeleteProcess( process_info_ptr& plist, pid_t pid );
__EXPORT process_info*	XCGetProcess   ( process_info_ptr plist, pid_t pid );
__EXPORT process_info*	XCMakeChild    ( XCAppInterface* app, char* file, process_info_ptr& plist, long pcount = 0, char** parms = NULL, bool usepipe = true, app_start_message* app_start = NULL );

__EXPORT void			XCWaitChildren ( XCAppInterface* app, int signum );
__EXPORT void			XCWaitForChildrenToExit();

__EXPORT int			XCShellExecute ( char* cmd );
__EXPORT int			XCExecuteAndWait( char* file, int pcount, char** parms );

// Critical section class
class __EXPORT XCCriticalSection : public XCBase {
public:
	XCCriticalSection();
	virtual ~XCCriticalSection();

	void Lock();
	void UnLock();
	bool TryLock();

private:
	OSDEP_CRITICAL_SECTION cs;
	OSDEP_MUTEX mutex;
};

enum XC_WAIT_RESULT {
	XCWAIT_OBJECT = 0,
	XCWAIT_TIMEOUT = 1
};

// Event object class
class __EXPORT XCEvent : public XCBase {
public:
	XCEvent( bool state );
	virtual ~XCEvent();

	void Wait();
	void Raise();

private:
	XC_EVENT_TYPE event;
	OSDEP_MUTEX mutex;
	bool waiting;
};

class __EXPORT XCManualEvent : public XCBase {
public:
	XCManualEvent( bool state=false );

	void Reset();
	void Raise();
	XC_WAIT_RESULT Wait( int timeout );
	bool GetState();

private:
	XC_EVENT_TYPE event;
	bool waiting;
};

// Thread local storage class
class __EXPORT XCTLS : public XCBase {
public:
	XCTLS();
	~XCTLS();

	const void* GetData();
	void SetData( const void* data );

private:
	OSDEP_TLS_INDEX index;
};

#endif	
